package com.codelee.soybean;



import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * common queryengine
 * Created by lic on 15/6/3.
 */
public class QueryEngine extends AbstractEngine{

    private RowProcessor processor;



    public QueryEngine(){
        this.processor = new BasicProcessor();
    }

    /**
     * select to bean
     * @param conn
     * @param sql
     * @param clazz
     * @param params
     * @param <T>
     * @return
     * @throws Throwable
     */
    public <T>T toBean(Connection conn,String sql, Class<? extends T> clazz, Object...params) throws Throwable{

        PreparedStatement ps = null;
        ResultSet rs = null;
        try{

            ps = super.preparedStatement(conn, sql, params);
            rs = ps.executeQuery();
            return this.processor.toBean(rs, clazz);
        }catch (Throwable e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                SoybeanUtils.close(rs);
                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }


        }


    }

    /**
     * select to bean List
     * @param conn
     * @param sql
     * @param clazz
     * @param params
     * @param <T>
     * @return
     * @throws Throwable
     */
    public <T>List<T> toBeanList(Connection conn,String sql, Class<? extends T> clazz, Object...params) throws Throwable{

        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> list = new ArrayList<T>();
        try{
            
            ps = super.preparedStatement(conn, sql, params);
            rs = ps.executeQuery();
            list =  this.processor.toBeanList(rs, clazz);
        }catch (Throwable e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                SoybeanUtils.close(rs);
                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return list;
    }

    /**
     * select to List Map
     * @param conn
     * @param sql
     * @param params
     * @return
     * @throws Throwable
     */
    public List<Map> toMapList(Connection conn, String sql, Object...params) throws Throwable{

        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Map> list = new ArrayList<Map>();
        try{
            
            ps = super.preparedStatement(conn, sql, params);
            rs = ps.executeQuery();
            list =  this.processor.toMapList(rs);
        }catch (Throwable e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                SoybeanUtils.close(rs);
                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return list;
    }

    /**
     * select to Map
     * @param conn
     * @param sql
     * @param params
     * @return
     * @throws Throwable
     */
    public Map toMap(Connection conn,String sql, Object...params) throws Throwable{

        PreparedStatement ps = null;
        ResultSet rs = null;
        Map map = new HashMap();
        try{

            ps = super.preparedStatement(conn, sql, params);
            rs = ps.executeQuery();
            map =  this.processor.toMap(rs);
        }catch (Throwable e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                SoybeanUtils.close(rs);
                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return map;
    }


    /**
     * select count
     * @param conn
     * @param sql
     * @param params
     * @return
     * @throws Throwable
     */
    public long count(Connection conn, String sql, Object...params) throws Throwable{

        PreparedStatement ps = null;
        ResultSet rs = null;
        long count = 0;
        try {

            ps = super.preparedStatement(conn, sql, params);
            rs = ps.executeQuery();
            count = this.processor.count(rs);
        }catch (Throwable e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                SoybeanUtils.close(rs);
                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return count;
    }


    /**
     * update insert delete
     * @param conn
     * @param sql
     * @param params
     * @return
     * @throws Throwable
     */
    public int update(Connection conn, String sql, Object...params) throws Throwable{

        PreparedStatement ps = null;
        int changes = 0;
        try {


            ps = super.preparedStatement(conn,sql,params);
            changes = ps.executeUpdate();

        }catch (Throwable e){

            e.printStackTrace();
            throw e;

        }finally {
            try {

                SoybeanUtils.close(ps);
                if(this.autoCommit){
                    SoybeanUtils.close(conn);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return changes;
    }


}
